bea34e
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2014 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,20 +31,23 @@
import org.springframework.util.ReflectionUtils;
  * Converts an entity identifier to a entity reference by calling a static finder method
  * on the target entity type.
  *
- * <p>For this converter to match, the finder method must be public, static, have the signature
+ * <p>For this converter to match, the finder method must be static, have the signature
  * {@code find[EntityName]([IdType])}, and return an instance of the desired entity type.
  *
  * @author Keith Donald
+ * @author Juergen Hoeller
  * @since 3.0
  */
 final class IdToEntityConverter implements ConditionalGenericConverter {
 
 	private final ConversionService conversionService;
 
+
 	public IdToEntityConverter(ConversionService conversionService) {
 		this.conversionService = conversionService;
 	}
 
+
 	@Override
 	public Set<ConvertiblePair> getConvertibleTypes() {
 		return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
@@ -53,7 +56,8 @@
final class IdToEntityConverter implements ConditionalGenericConverter {
 	@Override
 	public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
 		Method finder = getFinder(targetType.getType());
-		return finder != null && this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
+		return (finder != null &&
+				this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])));
 	}
 
 	@Override
@@ -62,18 +66,31 @@
final class IdToEntityConverter implements ConditionalGenericConverter {
 			return null;
 		}
 		Method finder = getFinder(targetType.getType());
-		Object id = this.conversionService.convert(source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
+		Object id = this.conversionService.convert(
+				source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
 		return ReflectionUtils.invokeMethod(finder, source, id);
 	}
 
+
 	private Method getFinder(Class<?> entityClass) {
 		String finderMethod = "find" + getEntityName(entityClass);
-		Method[] methods = entityClass.getDeclaredMethods();
+		Method[] methods;
+		boolean localOnlyFiltered;
+		try {
+			methods = entityClass.getDeclaredMethods();
+			localOnlyFiltered = true;
+		}
+		catch (SecurityException ex) {
+			// Not allowed to access non-public methods...
+			// Fallback: check locally declared public methods only.
+			methods = entityClass.getMethods();
+			localOnlyFiltered = false;
+		}
 		for (Method method : methods) {
-			if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass)) {
-				if (method.getName().equals(finderMethod)) {
-					return method;
-				}
+			if (Modifier.isStatic(method.getModifiers()) && method.getName().equals(finderMethod) &&
+					method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass) &&
+					(localOnlyFiltered || method.getDeclaringClass().equals(entityClass))) {
+				return method;
 			}
 		}
 		return null;
